package com.kob.botrunningsystem.service.impl.utils;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class BotPool extends Thread {//继承多线程
    private final ReentrantLock lock = new ReentrantLock();//加锁
    private final Condition condition = lock.newCondition();//条件变量（队列为空，就阻塞线程，不空就读取出来）
    //生产者不断加任务，消费者不断取任务，这两个线程对bot队列有读写冲突
    private final Queue<Bot> bots = new LinkedList<>();//需要保护的bot队列，不断从里面写入和读取（涉及多线程读写）
    public void addBot(Integer userId, String botCode, String input) {//往队列里加入bot，该方法会在BotRunningServiceImpl中调用，所以用public
        lock.lock();
        try {
            bots.add(new Bot(userId, botCode, input));
            condition.signalAll();//每次加完bot，都要唤醒所有线程，让他们去消费
        } finally {
            lock.unlock();
        }
    }
    private void consume(Bot bot) {//把含代码的bot发送给消费者
        Consumer consumer = new Consumer();
        consumer.startTimeout(2000, bot);//前端每个操作等5s，所以两个bot，每个bot分2s
    }

    @Override
    public void run() {//多线程入口
        while (true) {//该线程是死循环，不断读取bot队列
            lock.lock();
            if (bots.isEmpty()) {//队列空，就阻塞进程
                try {
                    condition.await();//注意，这个await里面包含一个锁释放的操作，阻塞但不会一直占有锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    lock.unlock();
                    break;
                }
            } else {//队列不空
                Bot bot = bots.remove();//取出队头
                lock.unlock();//解锁，因为读已经结束了，
                consume(bot);  // （消费这个任务，里面是代码的编译工作）比较耗时，可能会执行几秒钟，所以要解锁，不能一直占有锁
            }
        }
    }
}
